package com.ytclub.subject.domain.service.impl;

import com.alibaba.fastjson.JSON;
import com.ytclub.subject.common.entity.PageResult;
import com.ytclub.subject.common.enums.IsDeletedFlagEnum;
import com.ytclub.subject.common.enums.SubjectLikedStatusEnum;
import com.ytclub.subject.common.util.LoginUtil;
import com.ytclub.subject.domain.convert.SubjectLikedBOConverter;
import com.ytclub.subject.domain.entity.SubjectLikedBO;
import com.ytclub.subject.domain.redis.RedisUtil;
import com.ytclub.subject.domain.service.SubjectLikedDomainService;
import com.ytclub.subject.infra.basic.entity.SubjectInfo;
import com.ytclub.subject.infra.basic.entity.SubjectLiked;
import com.ytclub.subject.infra.basic.service.SubjectInfoService;
import com.ytclub.subject.infra.basic.service.SubjectLikedService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 点赞表 领域service实现了
 *
 * @author HuangQi
 * @since 2024-04-24 07:10:54
 */
@Service
@Slf4j
public class SubjectLikedDomainServiceImpl implements SubjectLikedDomainService {

    @Resource
    private SubjectInfoService subjectInfoService;

    @Resource
    private SubjectLikedService subjectLikedService;

    @Resource
    private RedisUtil redisUtil;

    private static final String SUBJECT_LIKED_KEY = "subject.liked";

    private static final String SUBJECT_LIKED_COUNT_KEY = "subject.liked.count";

    private static final String SUBJECT_LIKED_DETAIL_KEY = "subject.liked.detail";

    /**
     * 添加 点赞表 信息
     *
     * @param subjectLikedBO 新增点赞信息
     * @return 是否新增成功
     */
    @Override
    public void add(SubjectLikedBO subjectLikedBO) {
        if (log.isInfoEnabled()) {
            log.info("SubjectLikedDomainServiceImpl.add.bo:{}", JSON.toJSONString(subjectLikedBO));
        }
        // 构建hashKey
        Long subjectId = subjectLikedBO.getSubjectId();
        String likeUserId = subjectLikedBO.getLikeUserId();
        Integer status = subjectLikedBO.getStatus();
        String hashKey = buildSubjectLikedKey(subjectId.toString(), likeUserId);

        // 放入redis中
        redisUtil.putHash(SUBJECT_LIKED_KEY, hashKey, status.toString());

        // 判断是否是点赞状态
        String countKey = SUBJECT_LIKED_COUNT_KEY + "." + subjectId;
        String detailKey = SUBJECT_LIKED_DETAIL_KEY + "." + subjectId + "." + likeUserId;

        if (SubjectLikedStatusEnum.LIKED.getCode() == status) {
            // 点赞状态 点赞数+1,添加用户点赞状态
            redisUtil.increment(countKey, 1);
            redisUtil.set(detailKey, "1");
        } else {
            // 取消点赞状态 点赞数-1,删除用户点赞状态
            // 获取点赞数 如果点赞数不存在或者小于等于0 直接返回
            Integer count = redisUtil.getInt(countKey);
            if (Objects.isNull(count) || count <= 0) {
                return;
            }
            redisUtil.increment(countKey, -1);
            redisUtil.del(detailKey);
        }

    }

    /**
     * 获取题目是否被某个用户点赞过
     *
     * @param subjectId 题目id
     * @param userId    用户id
     * @return 是否被点赞过
     */
    @Override
    public Boolean isLiked(String subjectId, String userId) {
        String detailKey = SUBJECT_LIKED_DETAIL_KEY + "." + subjectId + "." + userId;
        boolean exist = redisUtil.exist(detailKey);
        if (exist) {
            return true;
        } else {
            // 查询数据库
            SubjectLiked subjectLiked = new SubjectLiked();
            subjectLiked.setSubjectId(Long.valueOf(subjectId));
            subjectLiked.setLikeUserId(userId);
            subjectLiked.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
            SubjectLiked result = subjectLikedService.queryByCondition(subjectLiked);
            if (Objects.isNull(result)) {
                return false;
            }
            return result.getStatus() == SubjectLikedStatusEnum.LIKED.getCode();
        }
    }

    /**
     * 获取点赞数量
     *
     * @param subjectId 题目id
     * @return 点赞数量
     */
    @Override
    public Integer getLikedCount(String subjectId) {
        String countKey = SUBJECT_LIKED_COUNT_KEY + "." + subjectId;
        Integer count = redisUtil.getInt(countKey);
        if (Objects.isNull(count) || count <= 0) {
            // 查询数据库
            count = subjectLikedService.queryCountBySubjectId(subjectId);
        }
        return count;
    }

    /**
     * 判断点赞表中是否存在
     *
     * @param subjectId 题目id
     * @param userId    用户id
     * @return 是否点赞
     */
    private SubjectLiked isExistLiked(Long subjectId, String likeUserId) {
        SubjectLiked subjectLiked = new SubjectLiked();
        subjectLiked.setSubjectId(subjectId);
        subjectLiked.setLikeUserId(likeUserId);
        subjectLiked.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        SubjectLiked result = subjectLikedService.queryByCondition(subjectLiked);
        return result;
    }

    /**
     * 更新点赞表
     *
     * @param subjectLikedBO 更新点赞信息
     * @return 是否更新成功
     */
    @Override
    public Boolean update(SubjectLikedBO subjectLikedBO) {
        if (log.isInfoEnabled()) {
            log.info("SubjectLikedDomainServiceImpl.update.bo:{}", JSON.toJSONString(subjectLikedBO));
        }
        // 参数转换
        SubjectLiked subjectLiked = SubjectLikedBOConverter.INSTANCE.convertBOToEntity(subjectLikedBO);

        // 调用service 返回结果
        return subjectLikedService.update(subjectLiked) > 0;
    }

    /**
     * 删除点赞表
     *
     * @param subjectLikedBO 删除点赞信息
     * @return 是否删除成功
     */
    @Override
    public Boolean delete(SubjectLikedBO subjectLikedBO) {
        if (log.isInfoEnabled()) {
            log.info("SubjectLikedDomainServiceImpl.delete.bo:{}", JSON.toJSONString(subjectLikedBO));
        }
        // 参数转换
        SubjectLiked subjectLiked = new SubjectLiked();
        subjectLiked.setId(subjectLikedBO.getId());
        subjectLiked.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode());

        // 调用service 返回结果
        return subjectLikedService.update(subjectLiked) > 0;
    }

    /**
     * 同步点赞数据
     */
    @Override
    public void syncLiked() {
        // 从redis中获取点赞数据并删除
        Map<Object, Object> subjectLikedMap = redisUtil.getHashAndDelete(SUBJECT_LIKED_KEY);
        if (log.isInfoEnabled()) {
            log.info("SubjectLikedDomainServiceImpl.syncLiked.subjectLikedMap:{}", JSON.toJSONString(subjectLikedMap));
        }
        // 判断是否为空
        if (MapUtils.isEmpty(subjectLikedMap)) {
            return;
        }

        // 不为空,批量同步到数据库
        List<SubjectLiked> subjectLikedList = new LinkedList<>();
        subjectLikedMap.forEach((key, value) -> {
            SubjectLiked subjectLiked = new SubjectLiked();
            // 拆分key
            String[] keyArr = key.toString().split(":");
            String subjectId = keyArr[0];
            String likedUser = keyArr[1];
            subjectLiked.setSubjectId(Long.valueOf(subjectId));
            subjectLiked.setLikeUserId(likedUser);
            subjectLiked.setStatus(Integer.valueOf(value.toString()));
            subjectLiked.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
            subjectLikedList.add(subjectLiked);
        });

        // 批量插入
        subjectLikedService.batchInsert(subjectLikedList);
    }

    /**
     * 获取我的点赞列表
     *
     * @param subjectLikedBO 查询条件
     * @return 点赞列表
     */
    @Override
    public PageResult<SubjectLikedBO> getSubjectLikedPage(SubjectLikedBO subjectLikedBO) {
        if (log.isInfoEnabled()) {
            log.info("SubjectLikedDomainServiceImpl.SubjectLikedBO.bo:{}", JSON.toJSONString(subjectLikedBO));
        }
        // 构建分页结果
        PageResult<SubjectLikedBO> pageResult = new PageResult<>();
        pageResult.setPageNo(subjectLikedBO.getPageNo());
        pageResult.setPageSize(subjectLikedBO.getPageSize());
        int start = (subjectLikedBO.getPageNo() - 1) * subjectLikedBO.getPageSize();

        // 参数转换
        SubjectLiked subjectLiked = SubjectLikedBOConverter.INSTANCE.convertBOToEntity(subjectLikedBO);
        subjectLiked.setLikeUserId(LoginUtil.getLoginId());
        // 查询总数
        int count = subjectLikedService.countByCondition(subjectLiked);
        if (count == 0) {
            return pageResult;
        }
        // 分页查询
        List<SubjectLiked> subjectLikedList = subjectLikedService.queryPage(subjectLiked, start,
                subjectLikedBO.getPageSize());

        // 转换结果
       List<SubjectLikedBO> subjectLikedBOList =  SubjectLikedBOConverter.INSTANCE.convertListInfoToBO(subjectLikedList);
       subjectLikedBOList.forEach(bo ->{
           SubjectInfo subjectInfo = subjectInfoService.queryById(bo.getSubjectId());
        bo.setSubjectName(subjectInfo.getSubjectName());
       });
        pageResult.setRecords(subjectLikedBOList);
        pageResult.setTotal(count);

        // 返回结果
        return pageResult;
    }

    /**
     * 构建点赞key
     *
     * @param subjectId 题目id
     * @param userId    用户id
     * @return hashKey
     */
    private String buildSubjectLikedKey(String subjectId, String userId) {
        return subjectId + ":" + userId;
    }

}
